#include "e2d/ui/GraphEditor.h"
#include "e2d/ui/State.h"

#include "e2d/core/render/CameraViewEdit.h"
#include "e2d/core/Entity.h"
#include "e2d/core/impl/components.h"

#include "e2d/imgui/Editor.h"

e2d::GraphEditor::GraphEditor()
	: fxcc::imgui::Layer("Editor")
{
	m_MarqueeSelection;

}

void e2d::GraphEditor::ViewFunc()
{
	auto& sg = e2d::State::Inst();

	if (!m_Scene)
	{
		return;
	}

	auto& io = ImGui::GetIO();
	io.ConfigFlags &= ~ImGuiConfigFlags_NavEnableKeyboard;
	
	ImVec2 m_ContentRegionAvail = ImGui::GetContentRegionAvail();
	ImVec2 contentPos = ImGui::GetCursorScreenPos();

	bool flag{ 0 };
	bool editCameraFlag = m_Scene->m_EditingCamera.m_Entity;
	bool hasCamera = editCameraFlag ? m_Scene->m_EditingCamera.m_Entity->HasComponent<e2d::CameraViewEdit>() : false;

	if (hasCamera)
	{
		auto& cameraViewObj = m_Scene->m_EditingCamera.m_Entity;
		auto& cameraView = cameraViewObj->Get<e2d::CameraViewEdit>();
		auto& cameraTransform = cameraViewObj->GetConst<e2d::TransformNode>();
		
		const auto& cameraProjMartix = cameraView.GetProjMatrix();
		const auto& cameraViewMartix = cameraTransform.m_World.GetViewMatrix();

		auto rt = cameraView.m_RenderTarget;

		auto texture = cameraView.GetTextureEditing();

		m_Editor.AddFrameBuffer(texture->GetTextureId());

		// Render Zmo
		ImGuizmo::SetOrthographic(cameraView.m_ProjData.m_IsOrtho);
		ImGuizmo::BeginFrame();
		ImGuizmo::SetDrawlist();

		float windowWidth = (float)ImGui::GetWindowWidth();
		float windowHeight = (float)ImGui::GetWindowHeight();
		ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, windowWidth, windowHeight);

		auto viewManipulateRight = ImGui::GetWindowPos().x + windowWidth;
		auto viewManipulateTop = ImGui::GetWindowPos().y;
		ImGuiWindow* window = ImGui::GetCurrentWindow();

		auto gizmoWindowFlags = ImGui::IsWindowFocused() && ImGui::IsMouseHoveringRect(window->InnerRect.Min, window->InnerRect.Max) ? ImGuiWindowFlags_NoMove : 0;

		for (auto it : m_Scene->m_AllEntitiesCalculated)
		{
			auto entity = m_Scene->m_EditingEntity.m_Entity;

			if (entity)
			{
				auto& transformNode = entity->GetOrEmplace<e2d::TransformNode>();

				glm::mat4 world = transformNode.GetWorldMatrix();

				bool flag = EditTransform(cameraProjMartix, cameraViewMartix, world);
				if(flag)
				{
					transformNode.SetWorldMatrix(world);
				}
				
			}
		}

		// OnPickup
		auto pickupRT = cameraView.m_PickRT;
		auto gBufferRT = cameraView.m_GBufferRT;

		if (IsMouseOnWindow() && pickupRT && !ImGuizmo::IsUsingAny())
		{
			//ImGui::IsMouseClicked(ImGuiMouseButton_Left)
			int mouseX = io.MousePos.x;
			int mouseY = io.MousePos.y;

			glm::vec2 posAxis{ 0.0f };

			posAxis.x = (float)(mouseX - contentPos.x) / (float)m_ContentRegionAvail.x;
			posAxis.y = (float)(mouseY - contentPos.y) / (float)m_ContentRegionAvail.y;

			posAxis.y = 1 - posAxis.y;

			posAxis.x = ImClamp(posAxis.x, 0.0f, 1.0f);
			posAxis.y = ImClamp(posAxis.y, 0.0f, 1.0f);

			int pickupIndex = pickupRT->GetPickupIndexAxis(0, posAxis);

			m_HoverEntity = cameraView.GetEntityByPickupIndex(pickupIndex);

			if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGuizmo::IsUsingAny())
			{

				if (m_HoverEntity)
				{
					sg.selectEntityFlag = true;
					sg.selectedEntity = m_HoverEntity;
					sg.m_CtrlSelect = io.KeyCtrl;
					sg.hireEntityFlag = true;
				}
				else 
				{
					sg.m_ClearAllSelected = true;
				}
			}
			
			if (m_HoverEntity)
			{
				bool hoverGridLayout = 
					m_HoverEntity->HasComponent<e2d::LayoutGrid>();

				for (const auto it : cameraView.m_EntityKeyMaps)
				{
					int key = ImGuiKey_0 + it.m_Keydown;
					if (ImGui::IsKeyPressed(ImGuiKey(key))) {
						ztclog::info("Key %d", key);
						
						auto newEntity = m_HoverEntity->NewChild();
						auto& prefeb = newEntity->GetOrEmplace<e2d::Prefeb>();
						prefeb.m_SourceEntity = it.m_EntityMap.m_Entity;

						if (hoverGridLayout)
						{
							if (m_HoverEntity->HasComponent<e2d::LayoutGrid>())
							{
								auto& floor = m_HoverEntity->Get<e2d::LayoutGrid>();
								auto& grid = newEntity->GetOrEmplace<e2d::Grid>();
								int offsetIndex = (pickupIndex - floor.m_PickupStartIndex);

								grid.m_GridIndex.x = offsetIndex / (floor.m_NumSep.y + 1);
								grid.m_GridIndex.y = offsetIndex % (floor.m_NumSep.y + 1) - 1;
								grid.m_GridIndex.z = 2;

							}
						}

						sg.m_LoadPrefebs = true;
					}
				}

			}
		}
	}

	ImGui::SetNextItemWidth(200);
	e2d::CustomEditor::ComboEditEntity("camera Editor", m_Scene->m_EditingCamera, m_Scene->GetComponentEntitiesMap<e2d::CameraViewEdit>());
	
	ImGui::SameLine();

	ImGui::SetNextItemWidth(200);
	e2d::CustomEditor::ComboEditEntity("camera Main", m_Scene->m_MainCamera, m_Scene->GetComponentEntitiesMap<e2d::CameraView>());


	io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
}

bool e2d::GraphEditor::EditTransform(const glm::mat4& proj, const glm::mat4& view, glm::mat4& world)
{
	ImGuiIO& io = ImGui::GetIO();
	float windowWidth = (float)ImGui::GetWindowWidth();
	float windowHeight = (float)ImGui::GetWindowHeight();
	bool useWindow = true;
	ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, windowWidth, windowHeight);
	return ImGuizmo::Manipulate(&view[0][0], &proj[0][0], ImGuizmo::TRANSLATE, ImGuizmo::WORLD, &world[0][0], NULL);
}


bool e2d::GraphEditor::GetMarqueeSelectionFlag()
{
	return !ImGuizmo::IsUsingAny();
}


void e2d::GraphEditor::HandleFunc()
{
}

void e2d::GraphEditor::RenderZmo()
{

}


